package com.wisewin.circle.util.wechat.xcx.util;

import org.apache.http.*;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.config.SocketConfig;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicHeader;
import org.apache.http.protocol.HttpContext;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import java.io.*;
import java.net.UnknownHostException;
import java.nio.charset.Charset;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.Map;

public class HttpRequestUtil {

    private static Header jsonHeader = new BasicHeader("Content-Type", ContentType.APPLICATION_JSON.toString());
    private static CloseableHttpClient httpClient;

    private static String requestPath = "https://api.weixin.qq.com";


    public static <T> T postWx(String url, String param, Class<T> clazz) {
        HttpUriRequest httpUriRequest = RequestBuilder.post().setHeader(jsonHeader).setUri(requestPath + url).setEntity(new StringEntity(param, Charset.forName("utf-8"))).build();
        return execute(httpUriRequest, JsonResponseHandler.createResponseHandler(clazz));
    }

    public static <T> T getWx(String url, Map<String, String> map, Class<T> clazz) {
        RequestBuilder requestBuilder = RequestBuilder.get().setHeader(jsonHeader).setUri(requestPath + url);
        for (String key : map.keySet()) {
            requestBuilder.addParameter(key, map.get(key));
        }
        return execute(requestBuilder.build(), JsonResponseHandler.createResponseHandler(clazz));
    }


    private static <T> T execute(HttpUriRequest request, ResponseHandler<T> responseHandler) {
        T execute = null;
        try {
            execute = httpClient.execute(request, responseHandler, HttpClientContext.create());
        } catch (Exception e) {

        }
        return execute;
    }


    static {
        httpClient = createHttpClient(100, 10, 8000, 2);
    }

    private static CloseableHttpClient createHttpClient(int maxTotal, int maxPerRoute, int timeout, int retryExecutionCount) {
        try {
            SSLContext sslContext = SSLContexts.custom().useSSL().build();
            SSLConnectionSocketFactory sf = new SSLConnectionSocketFactory(sslContext, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
            PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager();
            poolingHttpClientConnectionManager.setMaxTotal(maxTotal);
            poolingHttpClientConnectionManager.setDefaultMaxPerRoute(maxPerRoute);
            SocketConfig socketConfig = SocketConfig.custom().setSoTimeout(timeout).build();
            poolingHttpClientConnectionManager.setDefaultSocketConfig(socketConfig);
            HttpClientBuilder builder = HttpClientBuilder.create();
            return builder.setConnectionManager(poolingHttpClientConnectionManager).setSSLSocketFactory(sf).setRetryHandler(new HttpRequestRetryHandlerImpl(retryExecutionCount)).build();
        } catch (KeyManagementException var9) {
        } catch (NoSuchAlgorithmException var10) {
        }

        return null;
    }


    private static class HttpRequestRetryHandlerImpl implements HttpRequestRetryHandler {
        private int retryExecutionCount;

        public HttpRequestRetryHandlerImpl(int retryExecutionCount) {
            this.retryExecutionCount = retryExecutionCount;
        }

        public boolean retryRequest(IOException exception, int executionCount, HttpContext context) {
            if (executionCount > this.retryExecutionCount) {
                return false;
            } else if (exception instanceof InterruptedIOException) {
                return false;
            } else if (exception instanceof UnknownHostException) {
                return false;
            } else if (exception instanceof ConnectTimeoutException) {
                return true;
            } else if (exception instanceof SSLException) {
                return false;
            } else {
                HttpClientContext clientContext = HttpClientContext.adapt(context);
                HttpRequest request = clientContext.getRequest();
                boolean idempotent = !(request instanceof HttpEntityEnclosingRequest);
                return idempotent;
            }
        }
    }


    public static ByteArrayInputStream sendPost(String URL, String json) {
        InputStream inputStream = null;
        ByteArrayInputStream byteArrayInputStream = null;
        // 创建默认的httpClient实例.
        CloseableHttpClient httpclient = HttpClients.createDefault();
        // 创建httppost
        HttpPost httppost = new HttpPost(URL);
        httppost.addHeader("Content-type", "application/json; charset=utf-8");
        httppost.setHeader("Accept", "application/json");
        try {
            StringEntity s = new StringEntity(json, Charset.forName("UTF-8"));
            s.setContentEncoding("UTF-8");
            httppost.setEntity(s);
            HttpResponse response = httpclient.execute(httppost);
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
                // 获取相应实体
                HttpEntity entity = response.getEntity();
                inputStream = entity.getContent();
                ByteArrayOutputStream outStream = new ByteArrayOutputStream();
                // 创建一个Buffer字符串
                byte[] buffer = new byte[1024];
                // 每次读取的字符串长度，如果为-1，代表全部读取完毕
                int len = 0;
                // 使用一个输入流从buffer里把数据读取出来
                while ((len = inputStream.read(buffer)) != -1) {
                    // 用输出流往buffer里写入数据，中间参数代表从哪个位置开始读，len代表读取的长度
                    outStream.write(buffer, 0, len);
                }
                // 关闭输入流
                inputStream.close();
                // 把outStream里的数据写入内存
                byteArrayInputStream = new ByteArrayInputStream(outStream.toByteArray());
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 关闭连接,释放资源
            try {
                httpclient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return byteArrayInputStream;
    }

}
